package com.zhoug.zmui3;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.Shader;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.zhoug.common3.utils.LogUtils;
import com.zhoug.common3.utils.MathUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * 水球图
 * 全局样式 zmui_style_ZMUIWaveProgressView
 *
 * @Author 35574
 * @Date 2021/1/19
 * @Description
 */
public class ZMUIWaveProgressView extends View {
    private static final String TAG = ">>>ZMUIWaveProgressView";
    private static final boolean DEBUG = false;

    private static final int DEF_RADIUS = 300;
    /**
     * 外圆环的颜色
     */
    private int outCircleColor;
    /**
     * 内圆颜色
     */
    private int innerCircleColor;
    /**
     * 水波颜色
     */
    private int waveColor;
    /**
     * 外圆环粗细占水球半径的比例
     */
    private float outerRatio;
    /**
     * 内圆半径占水球半径的比例
     */
    private float innerRatio;

    private int textColor;

    private float textSize;


    /**
     * 水球半径:最短边长度的一半
     */
    private int mRadius;
    /**
     * 画笔
     */
    private Paint mPaint;
    private Paint mShaderPaint;
    private TextPaint mTextPaint;

    /**
     * 内圆渐变色数组
     */
    private int[] innerCircleColors;
    /**
     * 内圆渐变色数组的透明度
     */
    private static final int[] INNER_CIRCLE_COLORS_ALPHA = new int[]{0x00, 0x30, 0x80};
    /**
     * mInnerShader的 stops参数
     */
    private static final float[] INNER_CIRCLE_COLORS_STOPS = new float[]{0.00f, 0.9f, 1.0f};
    /**
     * 水球内边半径
     */
    private float mInnerRadius;
    private String[] texts;
    private int[] colors;

    /**
     * 水球
     */
    private Bitmap mWaveBitmap;
    /**
     * 水球画板
     */
    private Canvas mWaveCanvas;
    private Rect dst = new Rect();
    private Rect src = new Rect();
    private Paint mClearPaint;
    private float progress = 0f;//进度
    private float mCurProgress = progress;//进度
    private int pxOfDp;

    public ZMUIWaveProgressView(Context context) {
        this(context, null);
    }

    public ZMUIWaveProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.zmui_style_ZMUIWaveProgressView);
    }

    public ZMUIWaveProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZMUIWaveProgressView, defStyleAttr, R.style.zmui_style_ZMUIWaveProgressView);
        progress = a.getFloat(R.styleable.ZMUIWaveProgressView_zmui_progress, 0);
        outCircleColor = a.getColor(R.styleable.ZMUIWaveProgressView_zmui_outCircleColor, Color.GREEN);
        innerCircleColor = a.getColor(R.styleable.ZMUIWaveProgressView_zmui_innerCircleColor, Color.GREEN);
        waveColor = a.getColor(R.styleable.ZMUIWaveProgressView_zmui_waveColor, Color.parseColor("#a0ffffcc"));
        outerRatio = a.getFloat(R.styleable.ZMUIWaveProgressView_zmui_outerRatio, 0.05f);
        innerRatio = a.getFloat(R.styleable.ZMUIWaveProgressView_zmui_innerRatio, 0.8f);

        textColor = a.getColor(R.styleable.ZMUIWaveProgressView_android_textColor, Color.parseColor("#333333"));
        textSize = a.getDimension(R.styleable.ZMUIWaveProgressView_android_textSize, 20);

        a.recycle();

        setInnerCircleColor(innerCircleColor);
        setProgress(progress);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAntiAlias(true);

        mClearPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mClearPaint.setAntiAlias(true);

        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(textSize);
        mTextPaint.setColor(textColor);

        mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mShaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mShaderPaint.setAntiAlias(true);
        mShaderPaint.setStyle(Paint.Style.FILL);
        mShaderPaint.setStrokeWidth(1);

        pxOfDp = (int) (context.getResources().getDisplayMetrics().density + 0.5);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = measure(widthMeasureSpec);
        int height = measure(heightMeasureSpec);
        int size = Math.min(width, height);
        setMeasuredDimension(size, size);
    }

    private int measure(int measureSpec) {
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        int result = DEF_RADIUS;
        switch (mode) {
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                if (size > 0) {
                    result = size;
                }
                break;
            case MeasureSpec.EXACTLY:
                result = size;
                break;
        }
        return result;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mRadius = Math.min(w, h) >> 1;
        //水球内边半径
        mInnerRadius = mRadius * innerRatio;
        mWaveBitmap = Bitmap.createBitmap((int) (mInnerRadius * 2 + 0.5), (int) (mInnerRadius * 2 + 0.5), Bitmap.Config.ARGB_8888);
        mWaveCanvas = new Canvas(mWaveBitmap);
        //剪切为圆形
        Path path = new Path();
        path.addCircle(mWaveBitmap.getWidth() >> 1, mWaveBitmap.getHeight() >> 1, mInnerRadius, Path.Direction.CW);
        mWaveCanvas.clipPath(path);
        //水球边界渐变色
        //内圆为渐变色Shader
        RadialGradient mInnerShader = new RadialGradient(mWaveBitmap.getWidth() >> 1, mWaveBitmap.getHeight() >> 1, mInnerRadius,
                innerCircleColors, INNER_CIRCLE_COLORS_STOPS, Shader.TileMode.REPEAT);
        mShaderPaint.setShader(mInnerShader);
        src.left = 0;
        src.top = 0;
        src.right = mWaveBitmap.getWidth();
        src.bottom = mWaveBitmap.getHeight();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画外圆
        drawOuterCircle(canvas);
        //画波浪
        drawWave();
        //画文本
        drawText1();
        //画水球
        dst.left = (getWidth() - mWaveBitmap.getWidth()) >> 1;
        dst.top = (getHeight() - mWaveBitmap.getHeight()) >> 1;
        dst.right = dst.left + mWaveBitmap.getWidth();
        dst.bottom = dst.top + mWaveBitmap.getHeight();
        canvas.drawBitmap(mWaveBitmap, src, dst, null);
    }

    private float amplitudeY = 0.4f;//振幅
    private float mTranX = 0;//左右移动偏移量
    private Path mWavePath1 = new Path();
    private Path mWavePath2 = new Path();

    /**
     * 画水球
     */
    private void drawWave() {
        //清除画布
        mWaveCanvas.drawPaint(mClearPaint);
        //画水球边界

        mWaveCanvas.drawCircle(mWaveBitmap.getWidth() >> 1, mWaveBitmap.getHeight() >> 1, mInnerRadius, mShaderPaint);
        //根据进度计算水面的top
        float top = (1 - mCurProgress) * mWaveBitmap.getHeight();
        //画水平面
      /*  mPaint.setStrokeWidth(3);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.BLUE);
        mWaveCanvas.drawLine(0,top, mWaveCanvas.getWidth(),top,mPaint);*/
        //画波浪
        mWavePath1.reset();
        mWavePath2.reset();
        mWavePath1.moveTo(0, top);
        mWavePath2.moveTo(0, top);
        float x = 0;
        float y = 0, y2 = 0;
        //横坐标是弧度,纵坐标是sinx
        //计算出单位弧度所占的px
        float px = (float) (mWaveBitmap.getWidth() / 2 / Math.PI);
        float amplitudeX1 = 0.7f;//振幅x
        float amplitudeY1 = 0.2f;//振幅x
        float amplitudeX2 = 1.0f;//振幅x
        float amplitudeY2 = 0.3f;//振幅x

        while (x < mWaveBitmap.getWidth()) {
            y = (float) (Math.sin(x / px * amplitudeX1 + mTranX) * px * amplitudeY1);
            y2 = (float) (Math.sin(x / px * amplitudeX2 + mTranX) * px * amplitudeY2);
//            y = (float) (Math.sin(x / px * amplitudeX1 + mTranX) * 30*pxOfDp * amplitudeY);
//            y2 = (float) (Math.sin(x / px * amplitudeX2 + mTranX) *20*pxOfDp * (1 - amplitudeY));

            mWavePath1.lineTo(x, top - y);
            mWavePath2.lineTo(x, top - y2);
            x += 1;
        }
        closeWavePath(mWavePath1);
        closeWavePath(mWavePath2);
        mPaint.setStrokeWidth(1);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(waveColor);
        mWaveCanvas.drawPath(mWavePath1, mPaint);
        mWaveCanvas.drawPath(mWavePath2, mPaint);
    }


    private void closeWavePath(Path path) {
        path.lineTo(mWaveBitmap.getWidth(), mWaveBitmap.getHeight());
        path.lineTo(0, mWaveBitmap.getHeight());
        path.close();
    }

    /**
     * 画外圆
     *
     * @param canvas
     */
    private void drawOuterCircle(Canvas canvas) {
        float strokeWidth = mRadius * outerRatio;
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setColor(outCircleColor);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(getWidth() >> 1, getHeight() >> 1, mRadius - (strokeWidth / 2 + 1f), mPaint);
    }

    public void addText() {

    }


    private final float textSizePercent = 0.7f;
    private Paint.FontMetrics mFontMetrics = new Paint.FontMetrics();

    private void drawText1() {
        if (texts != null && texts.length > 0 && texts.length <= 2) {
            int height = mWaveCanvas.getHeight();
            int width = mWaveCanvas.getWidth();
            int rectH = (int) (height / texts.length);//按文本数据分成n分,每份的高度
            int centerX = width >> 1;
            int centerY = 0;
            mTextPaint.setTextAlign(Paint.Align.CENTER);
            mTextPaint.getFontMetrics(mFontMetrics);
            float h = mFontMetrics.descent - mFontMetrics.ascent;
            for (int i = 0; i < texts.length; i++) {
                String text = texts[i];
                centerY = rectH / 2 + i * rectH;
                mTextPaint.setColor(colors != null ? colors[i % colors.length] : textColor);
                mTextPaint.setFakeBoldText(true);
                mTextPaint.setTextSize(textSize);
//                mWaveCanvas.drawLine(0, centerY, width, centerY, mTextPaint);
                String progressText ;
                if (texts.length == 2 && i == 0) {
                    progressText = getProgressString(1-progress);
                } else {
                    progressText = getProgressString(progress);;
                }
                mWaveCanvas.drawText(progressText, centerX, centerY, mTextPaint);
                mTextPaint.setFakeBoldText(false);
                mTextPaint.setTextSize(textSize * textSizePercent);
                mWaveCanvas.drawText(text, centerX, centerY + h, mTextPaint);
            }
        }
    }

    private String getProgressString(float progress){
        if(progress==100){
            return "100%";
        }else if(progress==0){
            return "0%";
        }
        return MathUtils.getDecimal(progress * 100, 1) + "%";
    }


    /**
     * 画文本
     */
    /*private void drawText() {
        if (texts != null && texts.length > 0) {
            int height = mWaveCanvas.getHeight();
            int width = mWaveCanvas.getWidth();
            int rectH = (int) (height / texts.length);//按文本数据分成n分,每份的高度
            int centerX = width >> 1;
            int centerY = 0;
            mTextPaint.setTextAlign(Paint.Align.CENTER);
            for (int i = 0; i < texts.length; i++) {
                centerY = rectH / 2 + i * rectH;
                mWaveCanvas.drawLine(dst.left, centerY, dst.right, centerY, mTextPaint);
                CharSequence text = texts[i];
                if (text instanceof String) {
                    Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
                    float off = (fontMetrics.ascent + fontMetrics.descent) / 2;
                    mWaveCanvas.drawText(text, 0, text.length(), centerX, centerY - off, mTextPaint);
                } else if (text instanceof SpannableString) {
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                        DynamicLayout dynamicLayout = DynamicLayout.Builder.obtain(text, mTextPaint, width)
                                .setDisplayText(text)
                                .setIncludePad(true)
                                .setLineSpacing(1, 1)
                                .setAlignment(Layout.Alignment.ALIGN_NORMAL)
                                .build();
                        mWaveCanvas.save();
                        mWaveCanvas.translate(centerX, centerY);
                        dynamicLayout.draw(mWaveCanvas);
                        mWaveCanvas.restore();
                    } else {
                        mWaveCanvas.save();
                        mWaveCanvas.translate(centerX, centerY);
                        DynamicLayout dynamicLayout = new DynamicLayout(text, mTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, 1, true);
                        dynamicLayout.draw(mWaveCanvas);
                        mWaveCanvas.restore();
//                    }


                    }

                }


            }

        }
    }*/

    /**
     * 设置内圆颜色
     *
     * @param innerCircleColor
     */
    public void setInnerCircleColor(int innerCircleColor) {
        this.innerCircleColor = innerCircleColor;
        int red = Color.red(innerCircleColor);
        int green = Color.green(innerCircleColor);
        int blue = Color.blue(innerCircleColor);
        innerCircleColors = new int[INNER_CIRCLE_COLORS_ALPHA.length];
        for (int i = 0; i < INNER_CIRCLE_COLORS_ALPHA.length; i++) {
            innerCircleColors[i] = Color.argb(INNER_CIRCLE_COLORS_ALPHA[i], red, green, blue);
        }
    }

    private ValueAnimator animator;

    public void startWaveAnim() {
        stopWaveAnim();
        animator = ValueAnimator.ofFloat(0.0f, 0.9f);
        animator.setDuration(3000);
        animator.setInterpolator(new LinearInterpolator());
//        animator.setInterpolator(new AccelerateInterpolator());
        animator.setRepeatCount(-1);
        animator.setRepeatMode(ValueAnimator.REVERSE);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float curValue = (float) animation.getAnimatedValue();
                if (DEBUG) {
                    LogUtils.d(TAG, "onAnimationUpdate:curValue=" + curValue);
                }
                mTranX += 0.1;
//                amplitudeY = curValue;
                postInvalidate();
            }
        });
        animator.start();
    }

    public void stopWaveAnim() {
        if (animator != null) {
            animator.cancel();
            animator = null;
        }
    }

    public boolean isAnimRunning() {
        return animator != null && animator.isRunning();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        stopWaveAnim();
    }

    private boolean pauseAnim;

    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        if (visibility != VISIBLE) {
            if (isAnimRunning()) {
                pauseAnim = true;
                stopWaveAnim();
            } else {
                pauseAnim = false;
            }
        } else {
            if (pauseAnim) {
                pauseAnim = false;
                startWaveAnim();
            }
        }
    }

    /**
     * 从0开始动画
     *
     * @param during
     */
    public void startProgressAnim(int during) {
        mCurProgress = 0;
        ValueAnimator anim = ValueAnimator.ofFloat(0, progress);
        anim.setDuration(during);
        anim.setInterpolator(new LinearInterpolator());
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurProgress = (float) animation.getAnimatedValue();
                if (DEBUG) {
                    LogUtils.d(TAG, "onAnimationUpdate:mCurProgress=" + mCurProgress);
                }
                postInvalidate();
            }
        });
        anim.start();
    }

    /**
     * 设置进度(0-1.0f)
     *
     * @param progress
     */
    public void setProgress(float progress) {
        stopWaveAnim();
        this.progress = progress;
        this.mCurProgress = progress;
    }

    /**
     *从上次的进度递增/递减到新进度
     * @param progress 新进度
    * @param during 动画时间
     */
    public void animUpdateProgress(float progress,int during){
        stopWaveAnim();
        this.progress = progress;
        ValueAnimator anim = ValueAnimator.ofFloat(mCurProgress, progress);
        anim.setDuration(during);
        anim.setInterpolator(new LinearInterpolator());
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurProgress = (float) animation.getAnimatedValue();
                if (DEBUG) {
                    LogUtils.d(TAG, "onAnimationUpdate:mCurProgress=" + mCurProgress);
                }
                postInvalidate();
            }
        });
        anim.start();
    }

    /**
     * 设置文本:上,下
     * @param texts maxLength=2
     */
    public void setTexts(String... texts) {
        this.texts = texts;
    }

    /**
     * 设置文本
     *
     * @param colors maxLength=2
     */
    public void setTextColors(int... colors) {
        this.colors = colors;
    }

}
